package middleware

import (
	utils2 "go-pan/internal/utils"
	"net/http"
	"net/url"
	"strings"

	"github.com/gin-gonic/gin"
)

// CSRFMiddleware CSRF保护中间件
// 要求POST/PUT/DELETE/PATCH请求必须包含有效的CSRF token
func CSRFMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 排除登录、注册、登出和公开分享接口
		path := c.Request.URL.Path
		if path == "/api/v1/login" || path == "/api/v1/register" || path == "/api/v1/logout" ||
			strings.HasPrefix(path, "/api/v1/share/") {
			c.Next()
			return
		}

		// 只对写操作进行CSRF保护
		method := c.Request.Method
		if method == "GET" || method == "HEAD" || method == "OPTIONS" {
			c.Next()
			return
		}

		// 获取用户信息
		userInfo, ok := utils2.GetUserInfo(c)
		if !ok || userInfo == nil || userInfo.IsGuest {
			// 未登录用户不进行CSRF检查
			c.Next()
			return
		}

		// 从请求头获取CSRF token
		csrfToken := c.GetHeader("X-CSRF-Token")
		if csrfToken == "" {
			// 对于 multipart/form-data 请求，需要先解析表单
			contentType := c.ContentType()
			if strings.HasPrefix(contentType, "multipart/form-data") {
				// 解析 multipart 表单（32MB 限制）
				if err := c.Request.ParseMultipartForm(32 << 20); err == nil {
					csrfToken = c.PostForm("csrf_token")
				}
			} else {
				// 普通表单请求
				csrfToken = c.PostForm("csrf_token")
			}
			if csrfToken == "" {
				// 从 query 参数获取
				csrfToken = c.Query("csrf_token")
			}
		}

		if csrfToken == "" {
			c.JSON(http.StatusForbidden, gin.H{"error": "CSRF token required"})
			c.Abort()
			return
		}

		// URL 解码 CSRF token（Cookie 值可能被 URL 编码）
		decodedToken, err := url.QueryUnescape(csrfToken)
		if err == nil && decodedToken != csrfToken {
			csrfToken = decodedToken
		}

		// 验证CSRF token
		valid, err := utils2.ValidateCSRFToken(userInfo.ID, csrfToken)
		if err != nil || !valid {
			c.JSON(http.StatusForbidden, gin.H{"error": "invalid CSRF token"})
			c.Abort()
			return
		}

		c.Next()
	}
}
